﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using NopSolutions.NopCommerce.BusinessLogic.Products;
using NopSolutions.NopCommerce.BusinessLogic.Products.Specs;
using SimpleLucene;

namespace NopSolutions.NopCommerce.LuceneHelper.Definitions
{
    public class ProductDefinition : IIndexDefinition<Product>
    {
        public Lucene.Net.Documents.Document Convert(Product entity)
        {
            var minProductVariant = entity.MinimalPriceProductVariant;
            if (minProductVariant != null)
            {
                var document = new Document();
                document.AddField("Const", "1", Field.Index.NOT_ANALYZED, Field.Store.NO)
                    .AddField("Name", entity.Name)
                    .AddField("FullDescription", entity.FullDescription, Field.Index.ANALYZED, Field.Store.NO)
                    .AddField("ProductID", entity.ProductId.ToString(), Field.Index.NOT_ANALYZED)
                    .AddNumericField("SortOrder",
                                     minProductVariant.DisplayOrder == 0
                                         ? int.MaxValue
                                         : minProductVariant.DisplayOrder,
                                     Field.Store.NO, true)
                    .AddNumericField("Price", minProductVariant.Price, Field.Store.YES, true)
                    .AddNumericField("Rating",
                                     (entity.TotalRatingVotes > 0)
                                         ? decimal.Divide(entity.RatingSum, entity.TotalRatingVotes)
                                         : 0M,
                                     Field.Store.NO, true)
                    .AddField("UpdatedOn", DateTime.SpecifyKind(entity.UpdatedOn, DateTimeKind.Utc).ToString(new CultureInfo("en-US")));

                foreach (var manuId in entity.ProductManufacturers.Select(x => x.ManufacturerId))
                {
                    document.AddField("ManufacturerID", manuId.ToString(), Field.Index.NOT_ANALYZED, Field.Store.NO);
                }

                foreach (var c in entity.ProductCategories)
                {
                    var category = c.Category;
                    while (category != null)
                    {
                        document.AddField("CategoryID", category.CategoryId.ToString(), Field.Index.NOT_ANALYZED, Field.Store.NO);
                        category = category.ParentCategory;
                    }
                }
                var specIds = new List<int>();
                foreach (var productSpecOption in SpecificationAttributeManager.GetProductSpecificationAttributesByProductId(entity.ProductId))
                {
                    if (productSpecOption.AllowFiltering)
                    {
                        var specId = productSpecOption.SpecificationAttribute.SpecificationAttributeId;
                        document.AddField("Spec" + specId,
                                          productSpecOption.SpecificationAttributeOptionId.ToString(),
                                          Field.Index.NOT_ANALYZED, Field.Store.NO);
                        if (!specIds.Contains(specId))
                            specIds.Add(specId);
                    }
                }
                //These following fields are only so we can find products that have an option of a certain specification
                foreach (var specId in specIds)
                {
                    document.AddField("Specification", specId.ToString(), Field.Index.NOT_ANALYZED, Field.Store.NO);
                }
                return document;
            }
            return null;
        }

        public Lucene.Net.Index.Term GetIndex(Product entity)
        {
            return new Lucene.Net.Index.Term("ProductID", entity.ProductId.ToString());
        }

    }
}
